package savelog;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.Toast;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;

/**
  * Title: GameInfoFragment class for CSIS 343 Final Project 
 * Description: CS 343 Final Project - GameInfoFragment This class will handle displaying the list of saves for the chosen game in the GameListActivity
 * 
 * @author Erik Olson
 * @email erik.olson-5@my.uwrf.edu
 * @author Mike Harmon
 * @email michael.harmon@my.uwrf.edu
 * @author Jack Friermuth
 * @email jack.friermuth@my.uwrf.edu
 * @author Luke Vang
 * @email luke.vang@my.uwrf.edu
 * @author Casey Golla
 * @email casey.golla@my.uwrf.edu
 * @date December 4th 2012
 */

public class GameInfoFragment extends Fragment {
	//These are the layout components for the GameInfoFragment found inside the fragment_gameinfo_layout.xml
	private TableLayout saveTable;
	private TextView gTitle, gSystem;
	private ImageView gCover;
	private Button setSave;
	private Button uploadSave;

	//These are the storage variables for the Fragment containing data that our Buttons/TextViews use
	private String gameTitle, gameSystem, pathToBackup;
	private int gameID;
	private static ArrayList<Saves> saveArrayList;
	
	//These variables are used for how the Set
	private Hashtable<Integer, Boolean> hashtable;
	private int numChecked = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	/**
	 * Method the creates the view for the fragment
	 * @param LayoutInflator inflater, ViewGroup container, Bundle savedInstanceState
	 * @return view
	 * @Override
	 */
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_gameinfo_layout,	container, false);

		//Getting the TextViews in the Fragment layout
		gTitle = (TextView) view.findViewById(R.id.gameinfoTitle);
		gSystem = (TextView) view.findViewById(R.id.gameinfoSystem);

		//Getting the ImageView containing the game cover
		gCover = (ImageView) view.findViewById(R.id.gameinfoCover);

		//Getting the Set save button and setting its onClickListener
		setSave = (Button) view.findViewById(R.id.buttonSaveSet);
		setSave.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick(View v) {
				//If the number of saves selected is greater than 1
				if(numChecked < 1){
					Toast.makeText(getActivity(), "You must select 1 save to set as your current save.", Toast.LENGTH_SHORT).show();
				}
				//If the number of saves selected is greater than 1
				else if(numChecked > 1){
					Toast.makeText(getActivity(), "You can only set 1 save to be your current save.", Toast.LENGTH_SHORT).show();
				}
				else{
					swapSelectedSave();
				}
			}
		});
		
		//Getting the Upload save button and setting its onClickListener
		uploadSave = (Button) view.findViewById(R.id.buttonSaveUpload);
		uploadSave.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick(View v) {
				uploadSelectedSaves();
			}
		});

		//Getting the TableLayout for the saves from the Fragment layout
		saveTable = (TableLayout) view.findViewById(R.id.saveTable);

		//Setting the strings for the TextViews
		setGameInfo();

		//Creating the save TableLayout
		createSaveTable();

		return view;

	}

	/**
	 * Sets the Game and SaveList for the Fragment
	 * @param game	The game we are loading into GameInfoFragment
	 * @param gameSaves	The list of Saves for our Game
	 * @param backupPath	The path to the backup folder
	 */
	public void setGameInfoData(Games game, ArrayList<Saves> gameSaves, String backupPath) {
		gameTitle = game.getGame_title();
		gameID = game.getGame_id();
		gameSystem = "SNES";
		pathToBackup = backupPath;
		saveArrayList = gameSaves;
	}

	/**
	 * Sets the game title and system title text for the GameInfo TextViews
	 */
	public void setGameInfo() {
		gTitle.setText(gameTitle);
		gSystem.setText(gameSystem);
	}

	/**
	 * Gets the gameID for the currently selected game
	 * @return gameID The GameID of the currently displayed game
	 */
	public int getCurrentGameID() {
		return gameID;
	}

	/**
	 * Creates the TableLayout of Saves for GameInfo
	 */
	public void createSaveTable() {
		//Initializing a TableRow
		TableRow saveTableRow = null;
		hashtable = new Hashtable<Integer, Boolean>();

		//Looping through our saveArrayList and creating TableRows for each save
		for (int i = 0; i < saveArrayList.size(); i++) {
			saveTableRow = createSaveRow(i);
			saveTable.addView(saveTableRow);
		}
		//Setting it so the columns for the TableRows stretch to fill the available space
		saveTable.setStretchAllColumns(true);
	}

	/**
	 * Creates the TableRow for a single save
	 * @param i The index of the Save in the saveArrayList
	 * @return Returns the TableRow for the individual Save
	 */
	public TableRow createSaveRow(final int i) {
		//Getting the save we want for our TableRow
		Saves save = saveArrayList.get(i);

		//Initializing the layout parameters for the return TableRow
		TableRow.LayoutParams saveRowParams = new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

		//Initializing the return TableRow containing our save and setting the parameters
		TableRow returnTableRow = new TableRow(getActivity());
		returnTableRow.setLayoutParams(saveRowParams);
		
		//Using the layout inflater to get our reusable LinearLayout for our TableRow (savelist_row_layout.xml)
		LayoutInflater inflater = getActivity().getLayoutInflater();
		LinearLayout saveRowLinearLayout = (LinearLayout) inflater.inflate(R.layout.savelist_row_layout, returnTableRow, false);

		//Getting the CheckBox from the LinearLayout and setting the OnCheckChangedListener
		CheckBox saveCheckBox = (CheckBox) saveRowLinearLayout.findViewById(R.id.saveRowCheckBox);
		saveCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView,	boolean isChecked) {
				//If the CheckBox is NOW checked
				if (isChecked) {
					//Add the saveID of this save as a key to our hashtable of selected saves and adding true to the value, as it is selected
					hashtable.put(saveArrayList.get(i).getSave_id(), true);
					
					//Setting our LinearLayout to "selected" so the background lights up as selected for the whole TableRow
					((LinearLayout) buttonView.getParent().getParent()).setSelected(isChecked);
					
					//Incrementing our number checked for our Set save check
					numChecked++;
					
				} else {
					//Add the saveID of this save as a key to our hashtable of selected saves and adding false to the value, as it is not selected
					hashtable.put(saveArrayList.get(i).getSave_id(), false);
					
					//Un-Selecting our LinearLayout so that it is no longer highlighted, as it is not selected
					((LinearLayout) buttonView.getParent().getParent()).setSelected(isChecked);
					
					//Decrementing our number checked for our Set save check
					numChecked--;
				}

			}

		});

		//Getting the saveID TextView and setting its style and text
		TextView saveID = (TextView) saveRowLinearLayout.findViewById(R.id.saveRowID);
		String saveIDString = "" + save.getSave_id();
		saveID.setText(saveIDString);
		saveID.setTextAppearance(getActivity(), R.style.SaveListMain);

		//Getting the saveDate TextView and setting its style and text
		TextView saveDate = (TextView) saveRowLinearLayout.findViewById(R.id.saveRowDate);
		saveDate.setText(save.getSave_date_created());
		saveDate.setTextAppearance(getActivity(), R.style.SaveListMain);

		//Getting the saveDesc TextView and setting its style and text, currently the description is the date the save is added to the database
		TextView saveDesc = (TextView) saveRowLinearLayout.findViewById(R.id.saveRowDescrip);
		saveDesc.setText(save.getSave_descrip());
		saveDesc.setTextAppearance(getActivity(), R.style.SaveListDescrip);

		//Adding our LinearLayout for the save to our return TableRow and returning it
		returnTableRow.addView(saveRowLinearLayout);
		return returnTableRow;
	}

	/**
	 * A function to turn the desired amount of Density-Independent Pixels into pixels programmatically,
	 * as Density-Independent Pixels (dp) can't be calculated during runtime
	 * @param dp The value of dp that you wish returned in pixels
	 * @return The total pixels for the desired dp
	 */
	public int dpToPixels(int dp) {
		Resources r = getActivity().getResources();
		int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
		return px;
	}
	
	/**
	 * Our method to swap a selected Save from the backups directory to the ROMS directory for that game
	 */
	public void swapSelectedSave(){
		int saveToSwap;
		
		//Setting up our hashtable so that it's iterable using a Set filled with Entries
		Set<Entry<Integer, Boolean>> saveSet = hashtable.entrySet();	
		Iterator<Entry<Integer, Boolean>> saveSetIter = saveSet.iterator();
		
		//Iterating through our Set of selected Saves
		while(saveSetIter.hasNext()){
			//Getting the next entry in the set
			Hashtable.Entry<Integer, Boolean> entry = saveSetIter.next();
			
			//If the value of this entry is true, then this entry contains the save we have selected
			if(entry.getValue() == true){
				//The saveID of the Save we want to swap
				saveToSwap = entry.getKey();
				
				//Getting our Save
				Saves save = MainActivity.data.getSaveById(saveToSwap);
				
				//Swapping the save
				MainActivity.data.swapFile(save, pathToBackup);
				//Creating a Toast to let the user know that the Save was swapped successfully
				Toast.makeText(getActivity(), "Save successfully swapped!",	Toast.LENGTH_LONG).show();
			}
		}
	}
	
	/**
	 * Our method that is called to upload the selected Saves to our DropBox
	 */
	public void uploadSelectedSaves(){
		int saveID;
		
		//Getting the shared preferences to get our the Dropbox dir we wish to upload to
		SharedPreferences prefs = getActivity().getSharedPreferences(MainActivity.ACCOUNT_PREFS_NAME, Context.MODE_PRIVATE);
		String deviceName = prefs.getString("deviceName", "");
		String dbPath = "/" + deviceName + "/";
		//Setting up an empty List of Saves that we will add our selected Saves to
		List<Saves> savesToUpload = new ArrayList<Saves>();
		
		//Setting up our hashtable so that it's iterable using a Set filled with Entries
		Set<Entry<Integer, Boolean>> saveSet = hashtable.entrySet();	
		Iterator<Entry<Integer, Boolean>> saveSetIter = saveSet.iterator();
		
		//Iterating through our Set of selected Saves
		while(saveSetIter.hasNext()){
			//Getting the next entry in the set
			Hashtable.Entry<Integer, Boolean> entry = saveSetIter.next();
			
			//If the value of this entry is true, then this entry contains the save we have selected
			if(entry.getValue() == true){
				//The saveID of the Save we want to add to our savesToUpload List
				saveID = entry.getKey();
				
				//Getting our Save
				Saves save = MainActivity.data.getSaveById(saveID);
				
				//Adding the save to our List
				savesToUpload.add(save);
			}
		}
		//Initializing our Upload and uploading our List of Saves
		Upload upload = new Upload(getActivity(), MainActivity.mApi, dbPath);
		upload.execute(savesToUpload);
		
	}
}
